#pragma once
#include "expr.h"
class ExprBinaria :
	public Expr
{
public:

	ExprBinaria(Expr *left,Expr *right){
		this->left=left;
		this->right=right;
	}

	~ExprBinaria(void)
	{
	}

	Expr* getLeft(){
		return left;
	}

	void setLeft(Expr* left){
		this->left = left;
	}

	Expr* getRight(){
		return right;
	}

	void setRight(Expr* right){
		this->right = right;
	}

	void setis(int tokentype){
		TokenType tt;
		is_ = tt.returntokenstring(tokentype);

	}

	virtual string is(){
		return is_;
	}

	virtual tipo_ts * validarSemantica(tabla_simbolos *tabla_de_tipo,tabla_simbolos *tabla_de_varaible){
		tipo_ts *I = this->getLeft()->validarSemantica(tabla_de_tipo,tabla_de_varaible);
		tipo_ts *D = this->getRight()->validarSemantica(tabla_de_tipo,tabla_de_varaible);
		if(this->is_.compare("+")==0){
			if(I->is().compare("ENTERO") == 0){
				if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
					return D;
				}else{
					stringstream out;
					out<<"Tipo de datos incompatibles"<<endl;
					throw exception(out.str().c_str());
				}
			}else{
				if(I->is().compare("REAL") == 0){
					if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
					return I;
					}else{
						stringstream out;
						out<<"Tipo de datos incompatibles"<<endl;
						throw exception(out.str().c_str());
					}
				}else{
					if(I->is().compare("CADENA") == 0){
						if(D->is().compare("CADENA")==0){
						return I;
						}else{
							stringstream out;
							out<<"Tipo de datos incompatibles"<<endl;
							throw exception(out.str().c_str());
						}
					}else{
						stringstream out;
						out<<"Operacion No Valida"<<endl;
						throw exception(out.str().c_str());
					}
				}
			}
		}else{
			if(this->is_.compare("-")==0){
				if(I->is().compare("ENTERO") == 0){
				if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
					return D;
				}else{
					stringstream out;
					out<<"Tipo de datos incompatibles"<<endl;
					throw exception(out.str().c_str());
				}
			}else{
				if(I->is().compare("REAL") == 0){
					if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
					return I;
					}else{
						stringstream out;
						out<<"Tipo de datos incompatibles"<<endl;
						throw exception(out.str().c_str());
					}
				}else{
						stringstream out;
						out<<"Operacion No Valida"<<endl;
						throw exception(out.str().c_str());
					
				}
			}
			}else{
				if(this->is_.compare("O")==0){
					if(I->is().compare("ENTERO") == 0){
						if(D->is().compare("ENTERO")==0){
						return I;
						}else{
							stringstream out;
							out<<"Tipo de datos incompatibles"<<endl;
							throw exception(out.str().c_str());
						}
				}else{
						if(I->is().compare("BOOLEANO") == 0){
					if(D->is().compare("BOOLEANO")==0){
						return I;
						}else{
							stringstream out;
							out<<"Tipo de datos incompatibles"<<endl;
							throw exception(out.str().c_str());
						}
				}else{
						stringstream out;
						out<<"Operacion No Valida"<<endl;
						throw exception(out.str().c_str());
						}				
					}
				}else{
					if(this->is_.compare("Y")==0){
					if(I->is().compare("ENTERO") == 0){
						if(D->is().compare("ENTERO")==0){
						return I;
						}else{
							stringstream out;
							out<<"Tipo de datos incompatibles"<<endl;
							throw exception(out.str().c_str());
						}
				}else{
						if(I->is().compare("BOOLEANO") == 0){
					if(D->is().compare("BOOLEANO")==0){
						return I;
						}else{
							stringstream out;
							out<<"Tipo de datos incompatibles"<<endl;
							throw exception(out.str().c_str());
						}
				}else{
						stringstream out;
						out<<"Operacion No Valida"<<endl;
						throw exception(out.str().c_str());
						}				
					}
				}else{
						if(this->is_.compare("*")==0){
							if(I->is().compare("ENTERO") == 0){
								if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
									return D;
								}else{
									stringstream out;
									out<<"Tipo de datos incompatibles"<<endl;
									throw exception(out.str().c_str());
								}
								}else{
									if(I->is().compare("REAL") == 0){
										if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
											return I;
										}else{
											stringstream out;
											out<<"Tipo de datos incompatibles"<<endl;
											throw exception(out.str().c_str());
										}
									}else{
										stringstream out;
										out<<"Operacion No Valida"<<endl;
										throw exception(out.str().c_str());
									}
								}
							}else{
							if(this->is_.compare("/")==0){
								if(I->is().compare("ENTERO") == 0){
									if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
										return D;
									}else{
										stringstream out;
										out<<"Tipo de datos incompatibles"<<endl;
										throw exception(out.str().c_str());
									}
									}else{
										if(I->is().compare("REAL") == 0){
											if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
												return I;
											}else{
												stringstream out;
												out<<"Tipo de datos incompatibles"<<endl;
												throw exception(out.str().c_str());
											}
										}else{
											stringstream out;
											out<<"Operacion No Valida"<<endl;
											throw exception(out.str().c_str());
										}
									}
							}else{
								if(this->is_.compare("MOD")==0){
									if(I->is().compare("ENTERO") == 0){
										if(D->is().compare("ENTERO")==0){
											return D;
										}else{
											stringstream out;
											out<<"Tipo de datos incompatibles"<<endl;
											throw exception(out.str().c_str());
										}
									}else{
											stringstream out;
											out<<"Operacion No Valida"<<endl;
											throw exception(out.str().c_str());
									}
							}else{
									if(this->is_.compare("DIV")==0){
										if(I->is().compare("ENTERO") == 0){
											if(D->is().compare("ENTERO")==0){
												return D;
											}else{
												stringstream out;
												out<<"Tipo de datos incompatibles"<<endl;
												throw exception(out.str().c_str());
											}
										}else{
												stringstream out;
												out<<"Operacion No Valida"<<endl;
												throw exception(out.str().c_str());
										}
							}else{
										if(this->is_.compare("^")==0){
											if(I->is().compare("ENTERO") == 0){
												if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
													return D;
												}else{
													stringstream out;
													out<<"Tipo de datos incompatibles"<<endl;
													throw exception(out.str().c_str());
												}
											}else{
												if(I->is().compare("REAL") == 0){
													if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
														return I;
													}else{
														stringstream out;
														out<<"Tipo de datos incompatibles"<<endl;
														throw exception(out.str().c_str());
													}
												}else{
													stringstream out;
													out<<"Operacion No Valida"<<endl;
													throw exception(out.str().c_str());
					
												}
											}
										}else{
											if(this->is_.compare("MAYOR")==0 || this->is_.compare("MENOR")==0 || this->is_.compare("MENORIGUAL")==0 || this->is_.compare("MAYORIGUAL")==0 || this->is_.compare("IGUAL")==0 || this->is_.compare("DISTINTO")==0){
											if(I->is().compare("ENTERO") == 0){
												if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
													return tabla_de_tipo->get("BOOLEANO")->getTipo() ;
												}else{
													stringstream out;
													out<<"Tipo de datos incompatibles"<<endl;
													throw exception(out.str().c_str());
												}
											}else{
												if(I->is().compare("REAL") == 0){
													if(D->is().compare("ENTERO")==0 || D->is().compare("REAL")==0){
														return tabla_de_tipo->get("BOOLEANO")->getTipo() ;
													}else{
														stringstream out;
														out<<"Tipo de datos incompatibles"<<endl;
														throw exception(out.str().c_str());
													}
												}else{
													if(I->is().compare("CADENA") == 0){
														if(D->is().compare("CADENA")==0){
															return tabla_de_tipo->get("BOOLEANO")->getTipo() ;
														}else{
															stringstream out;
															out<<"Tipo de datos incompatibles"<<endl;
															throw exception(out.str().c_str());
														}
													}else{
														if(I->is().compare("CARACTER") == 0){
															if(D->is().compare("CARACTER")==0){
																return tabla_de_tipo->get("BOOLEANO")->getTipo() ;
															}else{
																stringstream out;
																out<<"Tipo de datos incompatibles"<<endl;
																throw exception(out.str().c_str());
															}
														}else{
															if(I->is().compare("BOOLEANO") == 0){
																if(D->is().compare("BOOLEANO")==0){
																	return tabla_de_tipo->get("BOOLEANO")->getTipo() ;
																}else{
																	stringstream out;
																	out<<"Tipo de datos incompatibles"<<endl;
																	throw exception(out.str().c_str());
																}
															}else{
																stringstream out;
																out<<"Operacion No Valida"<<endl;
																throw exception(out.str().c_str());
					
															}
					
														}
					
													}
					
												}
											}
										}else{
											stringstream out;
													out<<"Operacion no Soportada"<<endl;
													throw exception(out.str().c_str());
										}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}

private: 
	Expr *left;
	Expr *right;
	string is_;
};

